package com.potenza.edu.media.ws;

import com.potenza.edu.media.utils.HTMLFilter;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint("/websocket/chat/{loginName}")
@Component
public class ChatWebSocketEndPoint {

    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static final AtomicInteger onlineNum = new AtomicInteger(0);
    //concurrent包的线程安全Set，用来存放每个客户端对应的Session对象。
    private static final Set<ChatWebSocketEndPoint> connections = new CopyOnWriteArraySet<>();

    private String loginName;
    private Session session;
    /**
     * 当有ws 客户端连接进来，调用的方法
     * @param session
     */
    @OnOpen //创建一个websocket 就会执行OnOpen
    public void start(Session session, @PathParam("loginName")String loginName) {
        this.loginName = loginName;
        this.session = session;
        System.out.println("this:" + this);
        connections.add(this);

        onlineNum.incrementAndGet();//i++  ++i

        String msg = String.format("欢迎 %s(%s)加入，当前在线人数 %d",loginName,session.toString(),onlineNum.get());
        System.out.println(msg);

        broadcast(msg);//广播
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose //ws.close
    public void end(Session session,@PathParam("loginName")String loginName) {
        connections.remove(this);
        onlineNum.decrementAndGet();//i--
        String msg = String.format("%s(%s) 退出，当前在线人数 %d",loginName,session.toString(),onlineNum.get());
        System.out.println(msg);

        broadcast(msg);
    }

    /**
     * 接收到消息的监听方法
     * @param message
     */
    @OnMessage //ws.send
    public void incoming(Session session,String message,@PathParam("loginName")String loginName) {
        String msg = String.format("发送者%s(%s)发送消息： %s",loginName,session.toString(),message);
        System.out.println(msg);
        if(message.equals("北京南站怎么走")){
            broadcast("智能客服:" + "打车去吧");//
            //查询问题答案 ES，查不到 “对不起，请转人工”
        }else {
            broadcast(loginName + ":" + HTMLFilter.filter(msg));
        }
    }

    @OnError
    public void onError(Throwable t) throws Throwable {
        System.out.println("onError");
        t.printStackTrace();
    }

    /**
     * 广播消息
     * @param msg
     */
    private void broadcast(String msg) {
        for (ChatWebSocketEndPoint client : connections) {
            try {
                synchronized (client) {
                    client.session.getBasicRemote().sendText(msg);
                }
            } catch (IOException e) {
                connections.remove(client);
                try {
                    client.session.close();
                } catch (IOException e1) {
                    // Ignore
                }
                String message = String.format("* %s %s",
                        client.loginName, "has been disconnected.");
                broadcast(message);
            }
        }
    }
}
